package com.mapbased.sfw.model;

import java.io.IOException;
import java.text.SimpleDateFormat;
 
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import org.jboss.netty.buffer.ChannelBufferOutputStream;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.handler.codec.http.Cookie;
import org.jboss.netty.handler.codec.http.CookieDecoder;
import org.jboss.netty.handler.codec.http.CookieEncoder;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpHeaders;

import com.mapbased.sfw.common.Constants;
import com.mapbased.sfw.http.NettyHttpRequest;
import com.mapbased.sfw.ses.Session;
import com.mapbased.sfw.util.http.FastHttpDateFormat;

public class RenderContext {
	static protected SimpleDateFormat formats[] = {
			new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
			new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
			new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) };
	public static final String HTTP_RESPONSE_DATE_HEADER = "EEE, dd MMM yyyy HH:mm:ss zzz";
	public static final String SESSION_ID = "_sid";

	////////////////////////////////
	
	private SimpleDateFormat format;	//can resuse
	final public NettyHttpRequest req;
	final public DefaultHttpResponse resp;
	private Page urlPage;

	private Fragment currentFragment;
	Page currentMasterClient;
	Site site;
	private Set<Cookie> cookies;
	private Session session;
	private CookieEncoder setCookie;
	private     Map<String, Object> attributes;
	
	private Object [] vars;

	private Map<String, String> heads = new HashMap<String, String>();

	private ChannelBufferOutputStream os = new ChannelBufferOutputStream(
			ChannelBuffers.dynamicBuffer());

	// OutputStreamWriter osw=new OutputStreamWriter(os,Constants.PAGE_CHARSET);
	public RenderContext(NettyHttpRequest req, DefaultHttpResponse resp) {
		this.req = req;
		this.resp = resp;
		// this.decodeCookie();
	}
	public void setVar(int i,String v){
		this.vars[i]=v;
	}
	public void setVar(int i,int v){
		this.vars[i]=v;
	}
	public void setVar(int i,long v){
		this.vars[i]=v;
	}
	
	public Object getVar(int index){
		return this.vars[index];
	}
	public String getVarStr(int index){
		return String.valueOf( this.vars[index]);
	}
	public Site getSite(){
		return this.site;
	}
	public void addAttribute(String name,Object att){
		if(this.attributes==null){
			this.attributes=new    HashMap<String, Object>();
		}
		this.attributes.put(name, att);
	}
	public  Map<String, Object> getAttributes(){
		if(this.attributes==null){
			return Collections.emptyMap();
		}
		return this.attributes;
	}

	public void writeHeads() {
		for (String s : this.heads.values()) {
			this.write(s);
		}
	}

	public void addHead(String key, String value) {
		this.heads.put(key, value);
	}

	private void checkSetCookie() {
		if (this.setCookie == null) {
			this.setCookie = new CookieEncoder(true);
		}
	}

	public void addCookie(Cookie c) {

		this.checkSetCookie();
		this.setCookie.addCookie(c);
	}

	public void addCookie(String name, String value) {
		this.checkSetCookie();
		this.setCookie.addCookie(name, value);
	}

	public Cookie getCookie(String name) {
		if (this.cookies == null) {
			this.decodeCookie();
		}
		for (Cookie c : cookies) {
			if (c.getName().equals(name)) {
				return c;
			}
		}
		return null;
	}

	public Session getSession() {
		if (this.cookies == null) {
			this.decodeCookie();
		}
		return this.session;
	}

	public Session getSessionAllowCreate() {
		Session ses = this.getSession();
		if (ses == null) {
			ses = new Session();
			String sid = site.sessionStore.generateSessionId();
			this.addCookie(SESSION_ID, sid);
			this.site.sessionStore.putSession(sid, ses);
		}

		return ses;
	}

	public String getSessionId() {
		if (this.cookies == null) {
			this.decodeCookie();
		}
		for (Cookie c : cookies) {
			if (c.getName().equals(SESSION_ID)) {
				return c.getValue();
			}
		}
		return null;
	}

	private void decodeCookie() {
		CookieDecoder cd = new CookieDecoder();
		String ck = req.cookie();

		cookies = cd.decode(ck == null ? "" : ck);
		for (Cookie c : cookies) {
			if (c.getName().equals(SESSION_ID)) {
				String sid = c.getValue();
				session = site.sessionStore.getSession(sid);

			}
		}

	}

	public Page getUrlPage() {
		return urlPage;
	}

	public Page getCurrentMasterClient() {
		return currentMasterClient;
	}

	public void setUrlPage(Page urlPage) {
		this.urlPage = urlPage;
	}

	public String getPagePath() {
		return req.path();
	}

	public boolean isRenderFinished() {
		return this.os == null;
	}

	public void finishRender() {
		if (this.os != null) {

			if (this.setCookie != null) {
				resp.setHeader(HttpHeaders.Names.SET_COOKIE, this.setCookie
						.encode());

			}

			this.resp.setContent(os.buffer());
			resp.setHeader("Content-Length", resp.getContent().readableBytes());
			this.os = null;
		}
	}

	public void write(byte[] v) {
		try {
			os.write(v);
		} catch (IOException e) {
			throw new java.lang.RuntimeException(e);
		}

	}

	public void write(String v) {

		try {
			os.write(v.getBytes(Constants.PAGE_CHARSET));
		} catch (IOException e) {
			throw new java.lang.RuntimeException(e);
		}

	}

	public void setCurrentFragment(Fragment currentFragment) {
		this.currentFragment = currentFragment;
	}

	public Fragment getCurrentFragment() {
		return currentFragment;
	}

	public long getDateField(String name) {
		String value = this.req.header(name);
		if (value == null)
			return (-1L);

		// Attempt to convert the date header in a variety of formats
		long result = FastHttpDateFormat.parseDate(value, formats);
		if (result != (-1L)) {
			return result;
		}
		throw new IllegalArgumentException(value);

	}

	public void setDateField(String name, long date) {
		if (name == null || name.length() == 0) {
			return;
		}
		if (format == null) {
			format = new SimpleDateFormat(HTTP_RESPONSE_DATE_HEADER, Locale.US);
			format.setTimeZone(TimeZone.getTimeZone("GMT"));
		}

		this.resp.setHeader(name, FastHttpDateFormat.formatDate(date, format));
	}

}
